package org.aurora.common.util;

import org.apache.commons.cli.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;

public class CommandlineUtil {
    public static <T> T parseCommandLineConfig(String[] args, T object, Option option) throws Exception {
        DefaultParser parser = new DefaultParser();
        Options options = new Options();
        options.addOption(option);

        CommandLine commandLine = parser.parse(options, args);

        if (commandLine.hasOption(option)) {
            String configFile = commandLine.getOptionValue(option);

            if (StringUtils.isNotBlank(configFile)) {
                Properties properties = PropertiesUtil.loadConfig(configFile);

                properties2Object(properties, object);
            }
        }
        return object;
    }

    public static void properties2Object(Properties properties, Object object) throws InvocationTargetException, IllegalAccessException {
        Class<?> clazz = object.getClass();
        Method[] methods = clazz.getDeclaredMethods();

        for (Method method : methods) {
            String methodName = method.getName();

            if (methodName.length() > 3 && methodName.startsWith("set")) {
                String configParamName = methodName.substring(3, 4).toLowerCase() + methodName.substring(4);

                String property = properties.getProperty(configParamName);
                
                if (StringUtils.isNotBlank(property)) {
                    Class<?>[] parameterTypes = method.getParameterTypes();
                    if (parameterTypes.length == 1) {
                        Class<?> parameterType = parameterTypes[0];

                        String parameterTypeName = parameterType.getSimpleName();
                        Object arg = null;

                        if ((parameterTypeName.equals("int") || parameterTypeName.equals("Integer")) && NumberUtils.isDigits(property)) {
                            arg = Integer.parseInt(property);
                        } else if ((parameterTypeName.equals("long") || parameterTypeName.equals("Long")) && NumberUtils.isDigits(property)) {
                            arg = Long.parseLong(property);
                        } else if ((parameterTypeName.equals("double") || parameterTypeName.equals("Double")) && NumberUtils.isNumber(property)) {
                            arg = Double.parseDouble(property);
                        } else if ((parameterTypeName.equals("boolean") || parameterTypeName.equals("Boolean")) && ("true".equals(property) || "false".equals(property))) {
                            arg = Boolean.parseBoolean(property);
                        } else if ((parameterTypeName.equals("float") || parameterTypeName.equals("Float")) && NumberUtils.isNumber(property)) {
                            arg = Float.parseFloat(property);
                        } else if ((parameterTypeName.equals("String"))) {
                            property = property.trim();
                            arg = property;
                        }

                        if (arg != null) {
                            method.invoke(object, arg);
                        }
                    }
                }
            }
        }
    }
}
